class Node {
    constructor(element) {
        this.element = element;
        this.next = null;
    }
}

class NodeList {
    constructor() {
        this.head = null;
        this.length = 0;
    }
    /**
     * @description: get node 
     * @param {number} position
     * @return {Node}
     */
    getElementAt(position) {
        if (position < 0 || position > this.length) return null;
        let current = this.head;
        while (position-- > 0) {
            current = current.next;
        }
        return current;
    }
    /**
     * @description: 
     * @param {any} element
     * @return {NodeList}
     */
    append(element) {
        const node = new Node(element);
        if (this.head === null) this.head = node;
        else {
            let current = this.getElementAt(this.length - 1);
            current.next = node;
        }
        this.length++;
        return this;
    }
    /**
     * @description: 
     * @param {number} position
     * @param {any} element
     * @return {boolean}
     */
    insert(position, element) {
        if (position < 0 || position > this.length) return false;
        let node = new Node(element)
        if (position == 0) {
            node.next = this.head;
            this.head = node.next;
        } else {
            let current = this.getElementAt(position - 1);
            node.next = current.next;
            current.next = node;
        }
        this.length++;
        return true;
    }
    /**
     * @description: 
     * @param {number} position
     * @return {any}
     */
    removeAt(position) {
        if (position < 0 || position >= this.length) return null;
        let current = this.head;
        if (position == 0) {
            this.head = current.next;
        } else {
            let current = this.getElementAt(position - 1);
            current.next = current.next.next;
        }
        this.length--;
        return current.element;
    }
    /**
     * @description: 
     * @param {any} element
     * @return {number}
     */
    indexOf(element) {
        let current = this.head;
        for (let i = 0; i < this.length; i++) {
            if (current.element === element) return i;
            current = current.next;
        }
        return -1;
    }
    /**
     * @description: 
     * @param {any} element
     * @return {boolean}
     */
    remove(element) {
        const i = this.indexOf(element);
        if (i === -1) return false;
        this.removeAt(i);
        return true;
    }
    /**
     * @description: 
     * @param {*}
     * @return {*}
     */
    size() {
        return this.length;
    }
    /**
     * @description: 
     * @return {boolean}
     */
    isEmpty() {
        return this.length === 0;
    }
    /**
     * 
     * @returns 
     */
    getHead() {
        return this.head;
    }
    /**
     * 
     */
    clear() {
        this.head = null;
        this.length = 0;
    }
    toString() {
        let current = this.head.next;
        let s = '' + this.head.element;

        while (current) {
            s += '->' + current.element
            current = current.next;
        }
        return s;
    }
}

function print(val) {
    console.log(JSON.stringify(val, null, 2));
}

const a = new NodeList();
print(a)
a.append(1)
print(a)
a.insert(1, 2);
a.insert(1, 3);
print(a)
a.remove(1);
print(a)
console.log(a.toString())

